package main

import (
	"errors"
	"fmt"
	"io/fs"
	"log"
	"os"
	"os/exec"
	"time"

	"gitee.com/wmdng/vake/bond"
	"gitee.com/wmdng/vake/ninja"
	"gitee.com/wmdng/vake/parser"
)

func convert(ps []*parser.SExpre) (*ninja.Ninja, error) {

	nj := ninja.NewNinja()
	nj.SetReqVersion(1, 7)

	/**/
	err := bond.Convert(ps, nj)
	if err != nil {
		return nil, err
	}

	/**/
	return nj, nil
}

const (
	invake = "default.vake"
	oninja = "build.ninja"
)

func printUsage() {
	fmt.Printf("%s is tool to generate build.ninja, from default.vake\n", os.Args[0])
	fmt.Println("Usage:")
	fmt.Printf("\t%s build\n", os.Args[0])
	fmt.Printf("\t%s clean\n", os.Args[0])
	return
}

func main() {
	var otime time.Time

	/* check input vake exist. */
	infs, err := os.Stat(invake)
	if err != nil {
		fmt.Printf("%v\n", err)
		printUsage()
		os.Exit(1)
	}

	otfs, err := os.Stat(oninja)
	if err != nil {

		if errors.Is(err, fs.ErrNotExist) {

			fmt.Printf("%s is not exist..\n", oninja)
			/* the oldest time for compare */
			otime = time.Unix(0, 0)

		} else {
			fmt.Printf("%v\n", err)
			os.Exit(2)
		}

	} else {
		otime = otfs.ModTime()
		fmt.Printf("%s modtime, %v\n", oninja, otime)
	}

	/**/
	if infs.ModTime().After(otime) {

		fmt.Printf("%s need to be synchronized from %s...\n", oninja, invake)

		ps, err := parser.NewParser(invake)
		if err != nil {
			fmt.Println("init,", err)
			return
		}

		exps, perr := ps.GoThrou()
		if perr != nil {
			fmt.Printf("error : %s\n", perr.Error())
			return
		}

		// ps.Dump()
		/* parser tree to build.ninja file */
		nj, err := convert(exps)
		if err != nil {
			log.Fatal("convert:", err)
			//fmt.Println("convert:", err)
			return
		}

		/**/
		fp, err := os.Create(oninja)
		if err != nil {
			fmt.Println("create build.ninja:", err)
			return
		}

		nj.Dump(fp)
		fp.Close()
		
		/**/
		fmt.Println("synchronize succ..")

	} else {

		fmt.Printf("%s is already up to date.\n", oninja)
	}

	var cmm *exec.Cmd
	var arg string

	if len(os.Args) >= 2 {
		arg = os.Args[1]
	} else {
		arg = "build"
	}

	switch arg {

	case "build":
		cmm = exec.Command("ninja", "-v")

	case "clean":
		cmm = exec.Command("ninja", "-t", "clean")

	default:
		printUsage()
		return
	}

	/**/
	cmm.Stdout = os.Stdout
	cmm.Stderr = os.Stderr
	fmt.Printf(">>> %s\n", cmm.String())
	cmm.Run()

	/**/
	return
}
